#ifndef BM_LEVEL_H
#define BM_LEVEL_H
#include <stdio.h>
#include <stdlib.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#include "SDL/SDL.h"
#include "BM_anitex.h"
#include "BM_sound.h"

#define BLOCK_0	   0 //Nothing //NO FLOOR NO SPACE
#define BLOCK_1    1 //EMPTY SPACE with floor - with ceiling
#define BLOCK_2    2 //WALL with floor
#define BLOCK_3    3 //DOOR ACTIVATOR with floor
#define BLOCK_4    4 //ACTIVATED DOOR with floor
#define BLOCK_5    5 //DEACTIVATED DOOR with floor
#define BLOCK_6    6 //KEYDOOR  with floor
#define BLOCK_7    7 //KEY with floor
#define BLOCK_8    8 //KEYDOOR #3 with floor
#define BLOCK_9    9 //HINT BLOCK with floor
#define BLOCK_10    10 //START BLOCK (one only for now) with floor
#define BLOCK_11    11 //EXIT BLOCK (mulipty) with floor
#define BLOCK_12    12 // floor without ceiling
#define MAX_BLOCK_TYPES 11
#define MAX_BLOCKS_X	256
#define MAX_BLOCKS_Y	32
#define MAX_BLOCKS_Z	256
#define STARTING_POINTS	12

#define DRAW_TOP	0x01
#define DRAW_BOTTOM	0x02
#define DRAW_FRONT	0x04
#define DRAW_LEFT	0x08
#define DRAW_RIGHT	0x10
#define DRAW_BACK	0x20

typedef struct Point3D_s{
	float x, y, z;
} Point3D;

class BMBlock{
    private:
        float map_x, map_y, map_z;
        float x, y, z;
        float x_rot, y_rot, z_rot;
        int type;     //defines the type of block (wall, empty space with floor)
        int setting;    // setting
		int id;
		char dr;	//sides to draw
    public:
        BMBlock();
        void move(float q, float w, float s);
        void setMap(float q, float w, float s);
        void rotate(float q, float w, float s);
        int draw(GLuint texture, float scalar);
		void setType(int t);
		int getType();
		void setSetting(int s);
		int getSetting();
		void reset();
		void setDR(char d);
		char getDR();

};

class BMLevel{
    protected:
        BMAniTex ani_tex[MAX_BLOCK_TYPES];
        BMTex skybox_textures[6]; // BACK, FRONT, BOTTOM, TOP, LEFT, RIGHT
    private:
        float x, y, z;// level's x,y,z rotate (not used significantly at the moment)
        float x_rot, y_rot, z_rot; // level's x,y,z rotating (not used)
        float scalar; // level's scalar
		int width; // level's width
		int height; //level's height / 2 - 1
		int length; //level's length
		int depth; // level's depth - z axis
        char name[64]; // level name
        int time_total; // Time total
        int time_left; // How much time left
        int level; //Level Number
		float start[STARTING_POINTS][3]; // STARTING POINTS is the number of starting places a person can start at, 3 = x,y,z
		int total_start; // total number of starting points
        GLuint texture;
        char foldername[128];
        char cur_folder[128];
        BMBlock block[MAX_BLOCKS_X][MAX_BLOCKS_Y][MAX_BLOCKS_Z];
        float skybox_width, skybox_height, skybox_length, skybox_x, skybox_y, skybox_z;
		BMMusic song;
    public:
        BMLevel();
		~BMLevel();
		void begin();
		void end();
        void draw();
        int load(char filename[128]);
		int loadSmile();
        void move(float in_x, float in_y, float in_z);
        void rotate(float in_x, float in_y, float in_z);
        int readLevelHeader(FILE *file);
		void getStart(int i, float *sx, float *sy, float*sz);
		int collision(float cx, float cy, float cz, int xtra = -1);
		void freeLevel();
		void reset();
		float getScalar();
		int getDepth();
		void draw_skybox();
		void modify_skybox(float width, float height, float length);
		void move_skybox(float in_x, float in_y, float in_z);
		Point3D* getBlock(float cx, float cy, float cz);
		int getBlockType(int cx, int cy, int cz);
        //More to come

};


#endif
